#include <vector>
#include <algorithm>

typedef std::vector<int>::iterator IterT;
typedef std::vector<int>::const_iterator CIterT;


void tc1_notAGoodPractise()
{
	std::vector<int> values = { 1, 2, 10, 3, 8, 4 };

	//C++98 code
	IterT it = std::find(values.begin(), values.end(), 3);
	values.insert(it, 9);		// in C++98, vector::insert only accept iterator for the first parameter. 	
	//C++98 code has to make the compromise to use iterator. 

	//C++11 code
	CIterT cit = std::find(values.begin(), values.end(), 3);
	values.insert(cit, 9);		//C++11, vector::insert accepts const_iterator only	
}

void tc2_cxx11Practise()
{
	std::vector<int> values = { 1, 2, 10, 3, 8, 4 };

	auto ait = std::find(values.begin(), values.end(), 3);	//ait is iterator (not a const_iterator) because values is not const. 
	values.insert(ait, 9);		//it is still OK here, iterator is converted to const_iterator. 

	auto acit = std::find(values.cbegin(), values.cend(), 3);	//acit is a const_iterator now. 
	values.insert(acit, 9);		//that's the right way. 

	const std::vector<int>& cref_values = values;

	auto itCRef = std::find(cref_values.begin(), cref_values.end(), 3);	//itCRef is a const_iterator, because it is on a const container. 
	values.insert(itCRef, 9);
}

template <typename T>
auto cbegin(const T& container) -> decltype(std::begin(container))
{
	return std::begin(container);
}

void tc3_nonMemberBeginEnd()
{
	std::vector<int> values = { 1, 2, 10, 3, 8, 4 };
		
	auto it = std::begin(values);		//it is iterator, not a const_iterator

#ifndef __GNUC__
	auto cit = std::cbegin(values);		// c++11 std does not have this, but VS 2013 is support it.  
#else
	auto cit= cbegin(values);			// use the above template method.
#endif
}

int Test_I13_PreferConst_iteratorToIterator(int, char**)
{
	tc1_notAGoodPractise();
	tc2_cxx11Practise();
	tc3_nonMemberBeginEnd();

	return 0;
}

/*
Things to Remember
- Prefer const_iterators to iterators.
- In maximally generic code, prefer non-member versions of begin, end,
  rbegin, etc., over their member function counterparts.

*/
